/* ---------------------------------
 *  www.ittraining.com.tw
 * --------------------------------
 */

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus.h>
#include <limits.h>
//#define DEBUG 1

void dump_buf16( uint16_t *buf,int len);
void show_usage();
int modbus_read(int addr, int nb, uint16_t *rxbuf);
int modbus_write(int addr, int value);
int save_ee();
 modbus_t *ctx;

int main(int argc, char *argv[])
{
 
   
    int rc;
   uint16_t rxbuf[64];
   int count=1;
   int value=0;
   int action=0;

    errno = 0; 
   int reg_addr=100;
   
    if (argc>=4 && strcmp(argv[2],"r")==0) { //Modbus read

     reg_addr=atoi(argv[3])-1;
      if (argc==5)  count=atoi(argv[4]);
   } else if (argc==5 && strcmp(argv[2],"w")==0) {//Modbus write

     reg_addr=atoi(argv[3])-1;
     value=strtol(argv[4],NULL,16);
     action=1; 
   } else if (argc==3 && strcmp(argv[2],"save")==0) { //save to EEPROM in Palert
      action=2; 

  } else {
     show_usage();
   }


   ctx = modbus_new_tcp(argv[1], 502);
 
    if (ctx == NULL) {
        fprintf(stderr, "Unable to allocate libmodbus context\n");
        return -1;
    }
  #ifdef DEBUG 
   modbus_set_debug(ctx, TRUE);
   #endif

    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connection failed: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
    /** HOLDING REGISTERS **/
  if (action==0) {
    rc=modbus_read(reg_addr,count, rxbuf);
    if (rc<0) goto close;
    printf("Address:%d,Count=%d\n",reg_addr+1,count);
    dump_buf16(rxbuf,count);
   } else if (action==1)  {

    rc= modbus_write(reg_addr,value);
    if (rc<0) goto close;

   } else if (action==2)  {
     save_ee();
   }


close:

    /* Close the connection */
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}

void dump_buf16( uint16_t *buf,int len)
{
  int i=0;

  for (i=0;i<len;) {
     fprintf(stdout,"0x%X ",buf[i]);
    if (++i%16==0) printf("\n");
   }
  printf("\n");

}

int save_ee()
{

  return modbus_write(0x70,0x6);

}

int modbus_write(int addr, int value)
{
    int rc;
    rc = modbus_write_register(ctx, addr, value);
         printf(" modbus_write_register: ");
         if (rc == 1) {
         printf("OK\n");
    } else {
        printf("FAILED\n");
        return -1;

    }
    return rc;
}

int modbus_read(int addr, int nb, uint16_t *rxbuf)
{
    int rc;
    rc = modbus_read_registers(ctx,addr,nb,rxbuf);
  
    if (rc != nb) {
        printf("FAILED (nb points %d)\n", rc);
         return -1;
    } 
    
     
     return rc;
}

void show_usage()
{
     printf("Usage:\n");
     printf(" ./set_palert <IP> r [reg] [count]\n");
     printf(" ./set_palert <IP> w [reg] [value(Hex)]\n");
     printf(" ./set_palert <IP> save\n");
     exit(1);
}


